﻿/**
 * Rotation2D
 *
 * @author		Duarte Peixinho
 * @version		1.0
 */

package com.duartepeixinho.rotation 
{
	import flash.geom.Point;
	
	public class Rotation2D 
	{
		/**
		 * Rotation2D
		 */
		public function Rotation2D() {
			trace ("Rotation2D is a static class and should not be instantiated.");
		}
		
		/**
		 * Principal Function of rotation, returns an object with all rotated data
		 * @param	target			Object	Object to be rotated
		 * @param	angle			Object	Object that has the sin and cosine to rotate
		 * @param	rotationCenter	Point	Registration Point
		 * @param	reverse			Boolean	Reverse Rotation
		 * @return					Object	Object that contains all rotation values
		 */
		public static function rotate(target:Object, angle:Object, rotationCenter:Point, reverse:Boolean = false):Object {			

			//object
			var o:Object = new Object();
			
			//distance
			var dx:Number;
			var dy:Number;

			dx = target.x - rotationCenter.x;
			dy = target.y - rotationCenter.y;
			
			//distance calculation
			var dist:Number = Math.sqrt(dx * dx + dy * dy);
			
			//new x,y positions
			var x1:Number;
			var y1:Number;
			var doRotation:Point;
			//normal rotation
			if (!reverse) {
				//rotate
					doRotation = rotateValues(new Point(dx, dy), angle);
					//x new position
					x1 = doRotation.x;
					//y new position
					y1 = doRotation.y;
			}
			//reverse rotation
			else {
				//reverse rotate
				//x new position
				x1 = angle.cosine * dx + angle.sine * dy;
				//y new position
				y1 = angle.cosine * dy - angle.sine * dx;
			}
			
			//setting the object
			o.x = rotationCenter.x + x1;
			o.y = rotationCenter.y + y1;
			
			//only works with a static angle
			o.rotation = Math.atan2(dy, dx) * 180 / Math.PI;
			
			return o;	
		}		
		
		/**
		 * Similar to the principal, but it sets all the values directly to the target
		 * @param	target			Object		Object to be rotated
		 * @param	angle			Object		Object that has the sin and cosine to rotate
		 * @param	rotationCenter	Point		Registration point of the rotation
		 * @param	initialPosition	Point		Initial target's position
		 * @param	reverse			Boolean		Reverse rotation
		 */
		public static function copyPosition(target:Object, angle:Object, rotationCenter:Point, reverse:Boolean = false):void {
			var o:Object = rotate(target, angle, rotationCenter, reverse);
			target.x = o.x;
			target.y = o.y;
			target.rotation = o.rotation;			
		}
		
		/**
		 * calcAngle is a function that calculates sin and cosine of a given angle
		 * @param	angle	Number	Angle to be converted
		 * @return			Object	Object that contains sin and cosin of the angle
		 */
		public static function calcAngle(angle:Number):Object {
			var o:Object = new Object();
			o.sine = Math.sin(angle);
			o.cosine = Math.cos(angle);
			
			return o;
		}
		
		/**
		 * rotate values is a function that rotates a given coordinates by a given angle in radians
		 * @param	values	Point	Values to be Converted
		 * @param	angle	Object	Object that has the sin and cosine to rotate
		 * @param	reverse	Boolean	Reverse rotation
		 * @return			Point	Point whit rotated coordinates
		 */
		public static function rotateValues(values:Point,angle:Object,reverse:Boolean = false):Point {			
			var x:Number;
			var y:Number;

			if (!reverse) {
				x = angle.cosine * values.x - angle.sine * values.y;
				y = angle.cosine * values.y + angle.sine * values.x;
			}
			else {
				x = angle.cosine * values.x + angle.sine * values.y;
				y = angle.cosine * values.y - angle.sine * values.x;	
			}
			return new Point(x, y);
		}
	}
	
}